
/**
 * 防抖
 * @param fn         防抖的函数
 * @param delay      时间
 * @returns
 */
export const debounce = (fn: Function, delay: number) => {
  let timer: NodeJS.Timeout // Node.js的定时器类型

  // 定义func内部函数
  const func = function () {
    if (timer) clearTimeout(timer) // 定时器存在直接清除
    
    timer = setTimeout(() => {
      fn.apply(func, arguments) //delay毫秒内执行fn，将动态参数携带过去
    }, delay) // 创建新的定时器
  }
  return func // 返回的内部函数会在delay时间内执行一次fn
}



/**
 * 节流
 * @param fn         节流的函数
 * @param delay      时间
 * @returns
 */
export const throttle = (fn: Function, delay: number) => {
  let lastCallTime: number = 0; // 初始化上次函数调用的时间戳
  let timer: NodeJS.Timeout; // Node.js的定时器类型

  // 定义func内部函数，args剩余参数捕获实参
  const func = function (...args: any[]) {
    const now = Date.now(); //获取当前时间戳
    
    // 如果距离上次调用已经超过了 delay 时间，那么函数会立即执行，并且更新 lastCallTime 和清除定时器。
    if (now - lastCallTime >= delay) {
      if (timer) clearTimeout(timer); // 定时器存在直接清除
      fn.apply(this, args); //delay毫秒内执行fn，将剩余参数携带过去
      lastCallTime = now; // 更新次此函数执行的时间
      timer = null; // 确保清除定时器 
    } 
    // 如果距离上次调用还不到 delay 时间，那么设置一个定时器来稍后执行函数。
    else if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);  // 判断延迟时间delay距离上次执行毫秒内立即执行fn，将动态参数携带过去
        lastCallTime = Date.now(); // 更新次此函数执行的时间
        timer = null; // 确保清除定时器 
      }, delay - (now - lastCallTime)); // 创建新的定时器
    }
  };

  return func; // 返回的内部函数会在delay时间后执行一次fn
};

/**
 * 深拷贝函数
 * @param obj 
 * @returns 
 */
const deepCopy = (obj: any) => {
  // 判断传入的值是否为一个对象
  if (obj === null && typeof obj !== "object") {
    return obj;
  }
  // 判断对象的类型 注意这里不考虑包装类对象
  if (Object.prototype.toString.call(obj) === "[object Date]") {
    return new Date(obj);
  }
  if (Object.prototype.toString.call(obj) === "[object RegExp]") {
    return new RegExp(obj);
  }
  if (Object.prototype.toString.call(obj) === "[object Undefined]") {
    return new Error(obj);
  }
  // 判断对象是类
  let newObj = Array.isArray(obj) ? [] : {}
  for (let item in obj) {
    if (typeof obj[item] === 'object') {
      newObj[item] = deepCopy(obj[item])
    } else {
      newObj[item] = obj[item]
    }
  }
  return newObj
}

/**
 * 树转数组状数据
 * @param data 树数据
 * @param parentId 父级id
 * @returns 
 */
export function treeToArr(data: any[], parentId: string | number, res: any[] = []) {
  data.forEach(v => {
    res.push({
      ...v,
      id: v.id,
      parentId: parentId,
      name: v.name
    })
    if (v.children && v.children.length) {
      treeToArr(v.children, parentId, res)
    }
  })
  return res
}

/**
 * 数组转树状数据
 * @param data 数组数据
 * @param id 当前id
 * @param parentId 父级id
 * @param children 父级包含子级字段
 * @returns 
 */
export const arrToTree = (data, id: string = "id", parentId, children: string = "children") => {
  let result = [];
  if (!Array.isArray(data)) {
    return result;
  }
  // 清除已存在的children 重新赋值
  data.forEach(item => {
    delete item[children];
  });

  let map = {};
  data.forEach(item => {
    map[item[id]] = item;
  });

  data.forEach(item => {
    let parent = map[item[parentId]];
    if (parent) {
      (parent[children] || (parent[children] = [])).push(item);
    } else {
      result.push(item);
    }
  });
  return result;
};

/**
 * file转blob
 * @param data file
 * @returns blob
 */
export function fileToBlob(file) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.readAsArrayBuffer(file)
    let blob = null
    reader.onload = e => {
      if (typeof e.target.result === 'object') {
        blob = new Blob([e.target.result])
      } else {
        blob = e.target.result
      }
      resolve(blob)
    }
  })
}

/**
 * blob转file
 * @param data blob
 * @param data 文件名
 * @returns  file
 */
export function blobToFile(blob, name) {
  return new File([blob], name)
}

/**
 * blob转url
 * @param data blob
 * @returns  url
 */
export function blobToUrl(blob) {
  return window.URL.createObjectURL(blob)
}

/**
 * file转url
 * @param data file
 * @returns  url
 */
export function fileToUrl(file) {
  // eslint-disable-next-line no-async-promise-executor
  return new Promise(async resolve => {
    const blob = await fileToBlob(file)
    const url = blobToUrl(blob)
    resolve(url)
  })
}

/**
 * file转basee64
 * @param data file
 * @returns  basee64
 */
export function fileToBase64(file) {
  return new Promise(resolve => {
    let reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = function (e) {
      resolve(e.target.result)
    }
  })
}

/**
 * base64转blob
 * @param data base64
 * @returns  blob
 */
export function base64ToBlob(base64) {
  let arr = base64.split(',')
  let contentType = arr[0].match(/:(.*?);/)[1]
  let bstr = atob(arr[1])
  let n = bstr.length
  let u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new Blob([u8arr], { type: contentType })
}

/**
* @param: fileName - 文件名称
* @param: 数据返回 1) 无后缀匹配 - false
* @param: 数据返回 2) 匹配图片 - image
* @param: 数据返回 3) 匹配 txt - txt
* @param: 数据返回 4) 匹配 excel - excel
* @param: 数据返回 5) 匹配 word - word
* @param: 数据返回 6) 匹配 pdf - pdf
* @param: 数据返回 7) 匹配 ppt - ppt
* @param: 数据返回 8) 匹配 视频 - video
* @param: 数据返回 9) 匹配 音频 - radio
* @param: 数据返回 10) 其他匹配项 - other
**/
export const fileSuffixTypeUtil = {
  matchFileSuffixType(fileName: string) {
    // 后缀获取
    let suffix = ''
    // 获取类型结果
    let result: boolean | string = ''
    try {
      const flieArr = fileName.split('.')
      suffix = flieArr[flieArr.length - 1]
    } catch (err) {
      suffix = ''
    }
    // fileName无后缀返回 false
    if (!suffix) {
      result = false
      return result
    }
    // 图片格式
    const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp']
    // 进行图片匹配
    result = imglist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'image'
      return result
    }
    // 匹配txt
    const txtlist = ['txt']
    result = txtlist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'txt'
      return result
    }

    // 匹配 xlsx
    const xlsxlist = ['xlsx']
    // const excelist = ['xls', 'xlsx']
    result = xlsxlist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'xlsx'
      return result
    }
    // 匹配 xls
    const xlslist = ['xls']
    // const excelist = ['xls', 'xlsx']
    result = xlslist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'xls'
      return result
    }


    // // 匹配 excel
    // // const excelist = ['xlsx']
    // const excelist = ['xls', 'xlsx']
    // result = excelist.some(function (item) {
    //   return item == suffix
    // })
    // if (result) {
    //   result = 'excel'
    //   return result
    // }
    // 匹配 docx
    const docxlist = ['docx']
    // const wordlist = ['doc', 'docx']
    result = docxlist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'docx'
      return result
    }
    // 匹配 doc
    const doclist = ['doc']
    // const wordlist = ['doc', 'docx']
    result = doclist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'doc'
      return result
    }
    // // 匹配 word
    // const wordlist = ['docx']
    // // const wordlist = ['doc', 'docx']
    // result = wordlist.some(function (item) {
    //   return item == suffix
    // })
    // if (result) {
    //   result = 'word'
    //   return result
    // }
    // 匹配 pdf
    const pdflist = ['pdf']
    result = pdflist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'pdf'
      return result
    }
    // 匹配 ppt
    const pptlist = ['ppt']
    result = pptlist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'ppt'
      return result
    }
    // 匹配 视频
    const videolist = ['mp4', 'm2v', 'mkv']
    result = videolist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'video'
      return result
    }
    // 匹配 音频
    const radiolist = ['mp3', 'wav', 'wmv']
    result = radiolist.some(function (item) {
      return item == suffix
    })
    if (result) {
      result = 'radio'
      return result
    }
    // 其他 文件类型
    result = 'other'
    return result
  }
}
